<template>
  <div class="Chat">
    <!-- <div class="init-title">
      <p>很高兴见到你</p>
      <p>请在下方输入你想问我的问题吧</p>
    </div> -->
    <el-scrollbar class="scroll-view" ref="scrollMenuRes">
      <div v-for="(item,index) in msgList" :key="index">
        <!-- 用户 -->
        <div class="user-box">
          <el-row>
            <el-col :span="6"></el-col>
            <el-col class="content" :span="16">
              <div>{{ item.user }}</div>
            </el-col>
            <el-col :span="2">
              <img src="../assets/user.png" width="40" height="40">
              <!-- <el-avatar :size="40" src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png" /> -->
            </el-col>
          </el-row>
        </div>

        <!-- AI 回答 -->
        <div class="ai-box">
          <el-row>
            <el-col :span="2">
              <img src="../assets/yt-logo.png" width="40" height="40">
              <!-- <el-avatar :size="50" src="../assets/yt-logo.png" /> -->
            </el-col>
            <el-col class="content" :span="16">
              <!-- <div class="output" v-html="item.bot"></div> -->
               <!-- 生成回答和思考过程并用markdown组件显示-->
              <VMarkdownView :content="item.bot" ></VMarkdownView>
              <!-- 参考资料 -->
              <div v-if="!num">
                <!-- 图谱检索 -->
                <el-collapse :expand-icon-position="1" v-if="item.reference_graph.doc_pages.length != 0">
                  <el-collapse-item name="1">
                    <template #title>
                      <p class="reference-text"><b>图谱检索：</b></p>
                    </template>
                    <div class="demo-image__preview">
                      <!-- <p style="margin-bottom: 16px;"><b>图谱检索：</b></p> -->
                      <div v-for="(x, index) in item.reference_graph.doc_pages" :key="index">
                        <div style="margin: 0 0 12px 12px;"><b>{{ x.title }}</b></div>
                        <el-image
                          v-for="(url, i) in x.images" :key="i"
                          style="width: 100px; height: 100px;margin: 0 10px 10px 0;"
                          :src="url"
                          :zoom-rate="1.2"
                          :max-scale="7"
                          :min-scale="0.2"
                          :preview-src-list="[url]"
                          show-progress
                          :initial-index="1"
                          fit="cover"
                        />
                        <el-divider />
                      </div>

                    </div>
                  </el-collapse-item>
                </el-collapse>
                <!-- 图片检索 -->
                <el-collapse :expand-icon-position="2" v-if="item.reference_images.images != 0">
                  <el-collapse-item name="2">
                    <template #title>
                      <p class="reference-text"><b>图片检索：</b></p>
                    </template>
                    <div class="demo-image__preview">
                      <div>
                        <!-- <div style="margin: 0 0 12px 12px;"><b>{{ x.title }}</b></div> -->
                        <el-image
                          v-for="(url, i) in item.reference_images.images" :key="i"
                          style="width: 100px; height: 100px;margin: 0 10px 10px 0;"
                          :src="url"
                          :zoom-rate="1.2"
                          :max-scale="7"
                          :min-scale="0.2"
                          :preview-src-list="[url]"
                          show-progress
                          :initial-index="1"
                          fit="cover"
                        />
                        <VMarkdownView :content="item.reference_images.interpretation" ></VMarkdownView>
                        <el-divider />
                      </div>

                    </div>
                  </el-collapse-item>
                </el-collapse>
                <!-- 文本检索 -->
                <el-collapse :expand-icon-position="3" v-if="item.reference_text.length != 0">
                  <el-collapse-item name="3">
                    <template #title>
                      <p class="reference-text"><b>文本检索：</b></p>
                    </template>
                    <div class="text-style" v-html="item.reference_text"></div>

                  </el-collapse-item>
                </el-collapse>
              </div>


              <!-- 生成表单 2025.5.13先隐藏  -->
              <!-- <div v-if="item.reference_graph.chunks" class="table-content" v-html="item.chunks"></div> -->

            </el-col>
            <el-col :span="6"></el-col>
          </el-row>
        </div>

      </div>
    </el-scrollbar>

    <el-footer>
      <!-- <el-input type="textarea"></el-input> -->
      <div class="ask-box" style="max-width: 1000px"> 
        <el-input
          v-model="msgValue"
          :autosize="false"
          type="textarea"
          @keyup.enter="initStream"
          placeholder="请输入..."
          :disabled="inputDisabled"
        />
        <div class="btn-box">
          <el-button class="deep-search-btn" :class="{'deep-search': is_deep_search}" @click="changeDeepSearch" :disabled="inputDisabled"><el-icon><Opportunity /></el-icon>深度搜索</el-button>

          <el-button type="primary" @click="initStream" :disabled="inputDisabled">发送<el-icon><Promotion /></el-icon></el-button>
        </div>
      </div>
      <!-- <el-input
        class="question-input"
        v-model="msgValue"
        style="max-width: 1000px"
        placeholder="请输入..."
        @keyup.enter="initStream"
        :disabled="inputDisabled"
      >
        <template #append>
          <el-button @click="initStream"><el-icon><Promotion /></el-icon></el-button>
        </template>
      </el-input> -->
    </el-footer>
  </div>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
import { Promotion,Opportunity } from '@element-plus/icons-vue';

import axios from 'axios';
// import { Readable } from 'stream';
import data from '../utils/data.json'
import { fetchEventSource } from '@microsoft/fetch-event-source';
import { useRouter,useRoute } from 'vue-router';
// vue3可用的markdown组件
import { VMarkdownView } from 'vue3-markdown'
import 'vue3-markdown/dist/style.css'

let router = useRouter();
let route = useRoute();
let msgValue = ref('')
let session_id = ref(12)
let is_deep_search = ref(false)// 深度思考

let msgList = ref([
// {
//   "bot": "当然可以！不过您需要提供一下文章的内容或者主题，这样我才能根据具体内容给出一个准确、有用的评价。如果您能分享文章的主要内容、观点或题材，我会更好地为您服务！",
//   "user": "对这篇文章写个评价",
// },
// {
//   "bot": "雨夜，林深雾浓。年轻画家陆川撑着伞，走在荒废的山路上。他要去拜访一位隐居的老画家，传说那里的画作能预示未来。\n\n忽然，一阵冷风吹过，前方出现一个模糊的身影。是个女孩，浑身湿透，眼神空洞。“先生……请帮我找回家。”她的声音微弱却刺骨。陆川犹豫片刻，决定带她同行。\n\n到达破旧的木屋时，天已全黑。点燃蜡烛后，陆川发现女孩竟消失无踪，只留下一幅未完成的油画——画中的景象正是他刚才走过的路，而角落里多了一个撑伞的人影。\n\n深夜翻阅老画家留下的笔记，陆川才知这里几十年前溺亡过一名少女，而她的模样，与今晚遇见的女孩一模一样。",
//   "user": "写200字的小说",
// },
])
const content = ref('') // 界面向用户逐字输出的内容
const stringB = ref("") // 接口返回的完整内容
const url =   [
      "http://47.101.63.122:7500/gva/extract/extract_%E5%85%83%E9%80%9A%E6%B1%BD%E8%BD%A6%E4%B8%9A%E8%B4%A2%E7%A8%8E%E4%B8%80%E4%BD%93%E5%8C%96%E9%A1%B9%E7%9B%AE%E6%93%8D%E4%BD%9C%E6%89%8B%E5%86%8C-GMS-025-433_pdf/extracted_images/0055dcb0cf76d88fa0081e035b2858003cdf37ef7d50f4fc133393ac7f8afb5f.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=admin%2F20250509%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20250509T062937Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=6506f695a217553da089666a0059c7c8fbd5bcc078bbda91473e315ae2e79e85",
  ]
const srcList = ref(
  [
    [
                "http://47.101.63.122:7500/gva/extract/extract_元通汽车业财税一体化项目操作手册-GMS-025-433_pdf/pdf_2_images/output0001-353.jpg",
                "http://47.101.63.122:7500/gva/extract/extract_元通汽车业财税一体化项目操作手册-GMS-025-433_pdf/pdf_2_images/output0001-354.jpg",
                "http://47.101.63.122:7500/gva/extract/extract_元通汽车业财税一体化项目操作手册-GMS-025-433_pdf/pdf_2_images/output0001-355.jpg",
                "http://47.101.63.122:7500/gva/extract/extract_元通汽车业财税一体化项目操作手册-GMS-025-433_pdf/pdf_2_images/output0001-356.jpg",
                "http://47.101.63.122:7500/gva/extract/extract_元通汽车业财税一体化项目操作手册-GMS-025-433_pdf/pdf_2_images/output0001-357.jpg",
                "http://47.101.63.122:7500/gva/extract/extract_元通汽车业财税一体化项目操作手册-GMS-025-433_pdf/pdf_2_images/output0001-358.jpg",
    ],
    [
        "http://47.101.63.122:7500/gva/extract/extract_%E5%85%83%E9%80%9A%E6%B1%BD%E8%BD%A6%E4%B8%9A%E8%B4%A2%E7%A8%8E%E4%B8%80%E4%BD%93%E5%8C%96%E9%A1%B9%E7%9B%AE%E6%93%8D%E4%BD%9C%E6%89%8B%E5%86%8C-GMS-025-433_pdf/extracted_images/0055dcb0cf76d88fa0081e035b2858003cdf37ef7d50f4fc133393ac7f8afb5f.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=admin%2F20250509%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20250509T062937Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=6506f695a217553da089666a0059c7c8fbd5bcc078bbda91473e315ae2e79e85",
        "http://47.101.63.122:7500/gva/images/069dfedd-0b6d-4db4-8e0a-50f9f25eafd8_sample_page_18.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=admin%2F20250509%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20250509T063139Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=f9a87dbecebf8435405cf11481546a2d5a0defdc913d0ccfeff28ae7733e03ab",
    ]
  ]
) // 接口返回的完整内容
let chunksTxt = ref('')
let files = ref([])
let inputDisabled = ref(false)

const streamText = ref('');
let eventSource = null;
let scrollMenuRes = ref(null);
// 初始化 EventSource 连接
const initStream = () => {
let params = {
  session_id : session_id.value,        
  text : msgValue.value    
}
let new_msg  = {
  "bot": '思考中...',
  "user": msgValue.value,
  // 图谱检索
  "reference_graph":{
    "chunks":'',
    "doc_pages":''
  },
  // 图片检索
  "reference_images":{
    "images":[],
    "interpretation":''
  },
  // 文本检索
  "reference_text": []

}
let num = 0
msgList.value.push(new_msg)

const formData = new FormData()
formData.set('session_id', session_id.value)
formData.set('text', msgValue.value)
formData.set('is_deep_search', is_deep_search.value)
inputDisabled.value = true
const ctrlAbout = new AbortController();
eventSource = fetchEventSource('http://106.15.186.55:6008/api/v1/chat_bot/chatbot', {
  method: 'POST',
  headers: {
    'GVAPY-API-KEY': 'cf85a6770e16639f2388ea68c7d85d09',
    // 'Accept': "text/event-stream",
    // 这里不用设置 Content-Type，当你使用 FormData 时，fetch 会自动设置
    // "Content-type": "multipart/form-data;",
  },
  // body: JSON.stringify(params), // json用body
  body: formData, // form-data用data
  signal: ctrlAbout.signal,
  onmessage(event) {
    // console.log(event);
    // let picArr = JSON.parse(event.data).reference_graph.doc_pages
    // chunksTxt.value = ''
    // console.log(chunksArr)
    if(num === 0){
      msgList.value[msgList.value.length - 1].bot = ''
      let chunksArr = JSON.parse(event.data).reference_graph.chunks
      // 图片资料
      let reference_images = JSON.parse(event.data).reference_images
      // 文本资料
      let reference_text = JSON.parse(event.data).reference_text[0]
      let picArr = JSON.parse(event.data).reference_graph.doc_pages

      chunksArr.map(item=>{
        msgList.value[msgList.value.length - 1].reference_graph.chunks += item
      })
      // 图谱显示
      msgList.value[msgList.value.length - 1].reference_graph.doc_pages = JSON.parse(event.data).reference_graph.doc_pages
      // 图片显示
      msgList.value[msgList.value.length - 1].reference_images = reference_images
      // 文本显示
      msgList.value[msgList.value.length - 1].reference_text = reference_text

      // console.log(msgList.value[msgList.value.length - 1].doc_pages)
      // srcList.value = JSON.parse(event.data).reference_graph.doc_pages

      // chunksTxt.value = ''
      // console.log(msgList.value[msgList.value.length - 1].chunks)
      // console.log(chunksTxt.value)
    }
    if(JSON.parse(event.data).content){
      msgList.value[msgList.value.length - 1].bot += JSON.parse(event.data).content
    }
    num += 1

    // content.value += JSON.parse(event.data).content
    inputDisabled.value = false
    msgValue.value = ''
    scrollToBottom()

  },
  onerror() {
    console.log('err')
    inputDisabled.value = false
  }
})
};
// 文件上传
const handlePreview = (uploadFile) => {
  console.log(uploadFile)
}
const userQuestion = (question) => {
let msgValue = {
  text: question,
  msgFrom: 0,
  userId: 1
};
msgList.value.push(msgValue);
};
const AIReplay = (replay) => {
let autoReplyMsg = {
  text: replay,
  msgFrom: 1,
  userId: 1
};
msgList.value.push(autoReplyMsg);
};
// AI中的逐字输出
function print () {
// 如果向用户输出内容已经全部完成，则退出逐字输出
if (content.value.length >= stringB.value.length) {
  // 退出递归
  inputDisabled.value = false
  return;
} else {
  // content仍然比stringB短，进入下一次等待和递归
  setTimeout(() => {
    content.value += stringB.value.charAt(content.value.length);
    inputDisabled.value = true
    print(content, stringB);
  }, 50);
}
}

async function getHistory() {
  axios.get('http://106.15.186.55:6008/api/v1/chat_bot/histories/{session_id}?id=' + session_id.value, {
      headers: {
        'GVAPY-API-KEY': 'cf85a6770e16639f2388ea68c7d85d09',
      },
    }
  ).then(res => {
    if(JSON.stringify(res.data.data) == "{}"){
      msgList.value = []
    }else{
      msgList.value = res.data.data.history.message
    }
    if(route.query.key){
      msgValue.value = route.query.key
      // initStream()
    }
    // 滚动到底部
    nextTick(() => {
      scrollToBottom()
    },500);
    // scrollToBottom()
    console.log(msgList.value)
  })
}
//滚动面板自动滑动到底部
const scrollToBottom = () => {
if (scrollMenuRes.value) {
  const container = scrollMenuRes.value.$el.querySelector('.el-scrollbar__wrap');
  // console.log(scrollMenuRes.value.$el.querySelector('.el-scrollbar__view').height)
  container.style.scrollBehavior = 'smooth'; // 添加平滑滚动效果
  container.scrollTop = container.scrollHeight;
}
}
// 读取流式数据
async function readStream(reader) {
const decoder = new TextDecoder('utf-8');
while (true) {
  const { done, value } = await reader.read();
  if (done) break;

  // 解码数据并处理
  const message = decoder.decode(value);
  console.log('Received:', message);
}
}
function changeDeepSearch(){
  is_deep_search.value = !is_deep_search.value
}
onMounted(() => {
  if(route.query.id){ // 通过路由参数获取session_id
    session_id.value = route.query.id || 10
  }
  // Vue3中没有this，访问全局变量比较麻烦，手动获取this并挂载到window，页面中可以直接使用window.$this获取Vue实例
  getHistory()
  // nextTick(() => {
  //   let scrollElem = scrollMenuRes.value;
  //   scrollElem.scrollTo({ top: scrollElem.scrollHeight, behavior: 'smooth' });
  // });

})
</script>
<style lang="scss">
.Chat{
position: relative;
  .scroll-view{
    width: 65%;
    min-width: 800px;
    height: calc(100vh - 160px);
    margin: 0 auto;
  }
  .el-footer{
    position: fixed;
    bottom: 0;
    width: 87%;
    height: 160px;
    // border-top: 1px solid #ccc;
    padding: 10px;
    box-sizing: border-box;
    background: #fff;
    .question-input{
      margin: 40px 0;
      height: 40px;
    }
    .upload-demo{
      margin-top: 12px;
    }
  }
  .ask-box{
    position: relative;
    width: 1000px;
    // padding: 10px;
    height: 120px;
    // background: #c90;
    margin: 0 auto;
    // border: 1px solid #ccc;
    // border-radius: 5px;
    .el-textarea__inner{
      width: 100%;
      height:120px;
      padding-bottom: 40px;
      resize: none;
      border: none!important;
    }
    .btn-box{
      width: 100%;
      position: absolute;
      bottom: 0;
      margin-top: 10px;
      box-sizing: border-box;
      padding: 0 10px 5px;
      display: flex;
      justify-content: space-between;
      .deep-search-btn{
        width: 100px;
        height: 32px;
        border-radius: 5px;
        text-align: center;
        line-height: 32px;
        cursor: pointer;
        color:#333;
        border: 1px solid #ccc;
        border-radius: 4px;
        font-size: 14px;
        &.deep-search{
          background-color: #409EFF;
          color: #fff;
        }
      }
    }
  }
  .content{
    text-align: left;
    border-radius: 8px;
    background-color: #f5f7fa;
    padding: 10px;
    height: auto;
    .table-content{
      margin-top: 20px;
      background: #fff;
      padding: 20px;
      table{
        width: 100%;
        margin-bottom: 20px;
        td,th{
          border: 1px solid #000000;
          border-collapse: collapse;
          text-align: center;
        }
        border: 1px solid #000000;
        border-collapse: collapse;
        text-align: center;
      }

    }
  }
  .user-box{
    margin-bottom: 50px;
  }
  .ai-box{
    margin-bottom: 50px;
  }
  .markdown-body{
    padding: 12px;
  }
  .reference-text{
    padding: 12px;
    font-size: 16px;
  }
  .text-style{
    td{
      // border: 1px solid #333;
    }
  }
}
</style>